package com.cdks.wuxiu.api.service;

import lombok.extern.slf4j.Slf4j;

import java.util.List;

import javax.annotation.Resource;

import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;

import com.cdks.wuxiu.api.component.cdks.kmsg.SingleMessage;
import com.cdks.wuxiu.api.component.constant.Constant;
import com.cdks.wuxiu.api.model.dto.UserScoreDTO;
import com.cdks.wuxiu.api.model.dto.WalletInfoDTO;
import com.cdks.wuxiu.api.service.mysql.CallSheetInfoService;
import com.cdks.wuxiu.api.service.mysql.UserBillInfoService;
import com.cdks.wuxiu.api.service.mysql.UserLoginInfoService;
import com.cdks.wuxiu.api.service.mysql.UserScoreInfoService;
import com.cdks.wuxiu.api.service.mysql.UserStatisInfoService;
import com.cdks.wuxiu.api.service.mysql.UserWalletInfoService;
import com.cdks.wuxiu.api.service.mysql.VideoShowInfoService;
import com.cdks.wuxiu.api.service.mysql.VideoViewInfoService;
import com.cdks.wuxiu.api.service.redis.RedisService;
import com.cdks.wuxiu.api.util.SmsUtils;
import com.cdks.wuxiu.api.util.TimeUtils;
import com.cdks.wuxiu.entity.message.ChatPrivateData;
import com.cdks.wuxiu.entity.mysql.CallSheetInfo;
import com.cdks.wuxiu.entity.mysql.UserBaseInfo;
import com.cdks.wuxiu.entity.mysql.VideoShowInfo;
import com.cdks.wuxiu.entity.mysql.VideoViewInfo;


@Slf4j
@Service
public class VideoServiceImpl implements VideoService {
    @Resource
    private VideoShowInfoService videoShowInfoService; 
    @Resource
    private VideoViewInfoService videoViewInfoService;
    @Resource
    private UserLoginInfoService userLoginInfoService;
    @Resource
    private UserStatisInfoService userStatisInfoService;
    @Resource
    private CallSheetInfoService callSheetInfoService; 
    @Resource
    private UserWalletInfoService userWalletInfoService;   
    @Resource
    private UserScoreInfoService userScoreInfoService; 
    @Resource
    private UserBillInfoService userBillInfoService;            
    @Resource
    private RedisService redisService; 


    @Override
    public VideoShowInfo getVideoInfo(Long videoId) {
        return videoShowInfoService.getById(videoId);
    }
    
    @Override
    public List<VideoShowInfo> getUserVideos(long destId, Integer page) {
        return videoShowInfoService.getVideosByUser(destId, page);
    }

    @Override
    public int save(long userId, String videoUri, int status) {
        try {
            VideoShowInfo video  = new VideoShowInfo();
            video.setCreateTime(TimeUtils.getTimeSecond());
            video.setVideoUri(videoUri);;
            video.setUserId(userId);
            video.setStatus(status);

            videoShowInfoService.save(video);
        } catch (Exception e) {
            if (e instanceof DuplicateKeyException) {
                return -1;
            }
        }

        return 0;
    }

    @Override
    public int delete(long userId, String videoUri) {
        videoShowInfoService.deleteByName(userId, videoUri);

        return 0;
    }

    @Override
    public List<VideoShowInfo> getPlayList(long selfId, int sex) {
        return videoShowInfoService.getPlayList(selfId, sex);
    }

    @Override
    public int play(Long userId, String udid, long videoId) {
        videoShowInfoService.addPlayCount(videoId);
        userStatisInfoService.addVideoPlayCount(videoId);

        try {
            VideoViewInfo viewInfo  = new VideoViewInfo();
            viewInfo.setUdid(udid);
            viewInfo.setUserId(userId);
            viewInfo.setFileId(videoId);

            videoViewInfoService.save(viewInfo);
        } catch (Exception e) {
            return -1;
        }

        return 0;
    }

    @Override
    public int charge(Long videoId, UserBaseInfo userInfo, Integer cost) {
        long ret;
        long keepCost;


        //检查是否在通话中，如果在通话中，需要多预留一分钟通话费用
        long nowTime         = TimeUtils.getTimeSecond();
        CallSheetInfo sheet  = callSheetInfoService.getBusyCallByCaller(userInfo.getUserId());
        if (sheet != null)
        {
            //计费需要预留的费用（当前用户为通话主叫时，如果异常退出则可能存在应该结算而未结算的费用，所以要根据通话保持时间计算需要预留的费用）
            long callerTime  = redisService.getCallKeepTime(sheet.getCallerId(), sheet.getUcid());
            long answerTime  = redisService.getCallKeepTime(sheet.getAnswerId(), sheet.getUcid());
            long chargeTime  = Math.min(callerTime, answerTime);
            long startTime   = (sheet.getStartTime() > 0) ? sheet.getStartTime() : nowTime;
            long duration    = Math.min(nowTime, chargeTime + 60) - startTime;
            long minutes     = (duration + 59) / 60 + 1;
            
            keepCost  = minutes * sheet.getPayPrice() - sheet.getPayCost();
        }
        else
        {
            keepCost  = 0;
        }

        //获取可用余额。需要保证可用总余额（心豆 + 积分）>= 需要计费的总金额（通话预留+当前消费），否则有可能通话计费时需要抵扣的积分不足
        WalletInfoDTO wallet  = userWalletInfoService.getInfoWithScore(userInfo.getUserId(), nowTime);
        log.info("video reward: cost=" + cost + ", wallet=" + wallet);
        if ((wallet.getBean() + wallet.getScore()) < (cost + keepCost))
        {
            log.error("video reward charge failed: wallet = " + wallet + ", keepCost = " + keepCost + ", cost = " + cost);

            return -1;
        }

        long costBean;
        long costScore;
        int payType;
        if (wallet.getBean() < cost)
        {
            costBean   = wallet.getBean();
            costScore  = cost - wallet.getBean();
            payType    = Constant.COST_TYPE_SCORE;
        }
        else
        {
            costBean   = cost;
            costScore  = 0;
            payType    = Constant.COST_TYPE_BEAN;
        }

        //查询用户可用积分信息
        UserScoreDTO score  = userScoreInfoService.getBalanceByUser(userInfo.getUserId(), nowTime);
        log.info("video reward charge: score = " + score + ", keepCost = " + keepCost + ", costBean = " + costBean + ", costScore = " + costScore);
        if (score.getScore() < costScore)
        {
            return -2;
        }

        //先扣心豆
        if (costBean > 0)
        {
            //按预付费方式计费
            ret  = userWalletInfoService.decBean(userInfo.getUserId(), costBean, Constant.STATIS_TYPE_CONSUME, Constant.PAY_MODE_FIRST);
            if (ret < 0)
            {
                SmsUtils.sendManageNotice("视频秀计费异常");
                log.error("video reward update bean failed: userId = " + userInfo.getUserId() + ", costBean = " + costBean + ", ret = " + ret); 

                return -3;
            }
        }

        //再扣积分
        if (costScore > 0)
        {
            ret  = userScoreInfoService.decByUserId(userInfo.getUserId(), score.getMinId(), score.getMaxId(), costScore, nowTime);
            if (ret < 0)
            {
                SmsUtils.sendManageNotice("视频秀计费异常");
                log.error("video reward update score failed: userId = " + userInfo.getUserId() + ", score = " + score + ", costScore = " + costScore + ", ret = " + ret);

                return -4;
            }
        }

        VideoShowInfo videoInfo  = videoShowInfoService.getById(videoId);
        videoShowInfoService.addRewardCount(videoId);
   
        ChatPrivateData info  = new ChatPrivateData();
        info.setContent("用户[" + userInfo.getNickName() + "]打赏了您的视频秀，您收入" + cost + "金币，去跟用户聊聊吧~");
        info.setTitle("点击这里立即前往");
        info.setScheme("xinsu://chat/single?userId=" + userInfo.getUserId());
        SingleMessage.sendChatMessage(Constant.USERID_SYSTEM, videoInfo.getUserId(), Constant.MSG_TYPE_LINK, Constant.ENABLE_NO, info);
        SingleMessage.sendOfflineNotice(videoInfo.getUserId(), "视频秀打赏收入", info.getContent());

        //保存账单记录
        ret  = userBillInfoService.saveBill(cost, cost, costBean, costScore, cost, userInfo.getUserId(), videoInfo.getUserId(), payType, Constant.COST_TYPE_COIN, 0, "视频秀打赏");
        if (ret < 0)
        {
            log.error("video reward save bill failed");
        }
        else
        {
            //加收益
            userWalletInfoService.addCoin(videoInfo.getUserId(), cost, Constant.STATIS_TYPE_INWORK);            
        }

        return 0;
    }
}

